package xyz.xtt.user.service.impl;

import static xyz.xtt.common.asset.AssertUtils.isTrue;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.primitives.Longs;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.common.starter.cache.CacheManager;
import xyz.xtt.user.api.enums.UserStatus;
import xyz.xtt.user.client.request.UserRegRequest;
import xyz.xtt.user.client.response.UserRegResponse;
import xyz.xtt.user.constants.ErrorMessage;
import xyz.xtt.user.constants.UserCache;
import xyz.xtt.user.entity.TblUser;
import xyz.xtt.user.exception.ChainException;
import xyz.xtt.user.mapper.TblUserMapper;
import xyz.xtt.user.service.IInnerService;
import xyz.xtt.user.service.ITblUserService;
import xyz.xtt.user.service.ThirdService;
import xyz.xtt.user.utils.UserIdEncryptionUtil;
import xyz.xtt.user.vo.user.UserVo;

/**
 * <p>
 * 用户基础信息表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-10-17
 */
@Slf4j
@Service
public class TblUserServiceImpl extends ServiceImpl<TblUserMapper, TblUser> implements ITblUserService {
	@Autowired
	private IInnerService iInnerService;
	@Autowired
	private ThirdService thirdService;
	@Autowired
	private CacheManager cacheManager;
	private Integer guideValue = 1;

	@Override
	public TblUser info(Long uid) {
		return cacheManager
				.cacheObj(() -> new LambdaQueryChainWrapper<>(baseMapper).eq(TblUser::getAppUserId, uid).one(), UserCache.TBL_USER, String.valueOf(uid));
	}

	@Override
	public Long syncInfo(Long uid) {
		TblUser info = info(uid);
		return Objects.isNull(info) ? 0L : 1;
	}

	@Override
	public List<TblUser> userInfo(Collection<String> uids) {
		return new LambdaQueryChainWrapper<>(baseMapper).in(TblUser::getAppUserId, uids).list();
	}

	@Override
	public boolean updateUser(TblUser user) {
		if (Objects.isNull(user)) {
			log.info("updateUser is null");
			return false;
		}
		if (user.syncUpdateCheck()) {
			log.info("updateUser syncUpdateCheck() is true");
			return false;
		}
		LambdaUpdateChainWrapper<TblUser> update = new LambdaUpdateChainWrapper<>(baseMapper);
		update
				.eq(TblUser::getAppUserId, user.getUserId())
				.set(StringUtils.isNoneBlank(user.getAvatarUri()), TblUser::getAvatarUri, user.getAvatarUri())
				.set(StringUtils.isNoneBlank(user.getPhone()), TblUser::getPhone, user.getPhone())
				.set(StringUtils.isNoneBlank(user.getUserName()), TblUser::getUserName, user.getUserName());
		return update.update();
	}

	@Override
	public boolean updateUserStatusLogoff(Long appUid) {
		LambdaUpdateChainWrapper<TblUser> update = new LambdaUpdateChainWrapper<>(baseMapper);
		return update.eq(TblUser::getAppUserId, appUid).set(TblUser::getStatus, UserStatus.LOGOFF.getCode()).update();
	}

	@Override
	public TblUser infoWithPhone(String phone) {
		String ph = phone;
		if (!StringUtils.startsWith("86", phone)) {
			ph = "86" + phone;
		}
		List<TblUser> list = new LambdaQueryChainWrapper<>(baseMapper).in(TblUser::getPhoneBk, ph).list();
		if (CollectionUtil.isEmpty(list)) {
			return null;
		}
		if (list.size() == 1) {
			return list.get(0);
		}
		return list.stream().max(Comparator.comparing(TblUser::getRegisterDatetime)).orElse(null);
	}

	@Override
	public boolean autoRegUpdateUser(TblUser user) {
		if (Objects.isNull(user)) {
			log.info("autoRegUpdateUser is null");
			return false;
		}
		if (user.syncUpdateCheck()) {
			log.info("updateUser syncUpdateCheck() is true");
			return false;
		}
		LambdaUpdateChainWrapper<TblUser> update = new LambdaUpdateChainWrapper<>(baseMapper);
		update
				.eq(TblUser::getAppUserId, user.getUserId())
				.set(TblUser::getUserId, 0)
				.set(StringUtils.isNoneBlank(user.getAvatarUri()), TblUser::getAvatarUri, user.getAvatarUri())
				.set(StringUtils.isNoneBlank(user.getPhone()), TblUser::getPhone, user.getPhone())
				.set(StringUtils.isNoneBlank(user.getUserName()), TblUser::getUserName, user.getUserName());
		return update.update();
	}

	@Override
	@Async
	public void updateAuthByAppUserId(String appUserId, String userName, String idCardNo) {
		UpdateWrapper<TblUser> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("app_user_id", appUserId).set("user_name", userName).set("id_card_no", idCardNo);
		baseMapper.update(updateWrapper);
	}

	@Override
	@Async
	public void updateAuthStatusByAppUserId(String appUserId) {
		UpdateWrapper<TblUser> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("app_user_id", Long.valueOf(appUserId)).set("auth_status", 1).set("auth_before", System.currentTimeMillis());
		baseMapper.update(updateWrapper);
		cacheManager.delete(UserCache.TBL_USER, appUserId);
	}

	@Override
	public Boolean setUserGuide(Long userId) {
		TblUser tblUser = info(userId);
		if (Objects.isNull(tblUser)) {
			return true;
		}
		if (Objects.nonNull(tblUser.getGuide()) && guideValue.equals(tblUser.getGuide())) {
			return true;
		}
		// 更新数据
		LambdaUpdateChainWrapper<TblUser> updateWrapper = new LambdaUpdateChainWrapper<>(baseMapper);
		updateWrapper.eq(TblUser::getAppUserId, userId).set(TblUser::getGuide, guideValue);
		updateWrapper.update();
		// 删除缓存
		cacheManager.delete(UserCache.TBL_USER, String.valueOf(userId));
		return true;
	}

	@Override
	public UserVo getUserInfo(String uid) {
		LambdaQueryChainWrapper<TblUser> query = new LambdaQueryChainWrapper<>(baseMapper);
		TblUser tblUser = query.eq(TblUser::getAppUserId, Longs.tryParse(uid)).one();
		if (Objects.isNull(tblUser)) {
			return null;
		}
		UserVo userVO = new UserVo();
		userVO.setUid("" + tblUser.getAppUserId());
		userVO.setFakeUserId(UserIdEncryptionUtil.encrypt(tblUser.getAppUserId()));
		userVO.setNickname(tblUser.getNickname());
		userVO.setAvatar(tblUser.getAvatarUri());
		Long authBefore = tblUser.getAuthBefore();
		// 说明没有认证
		// 去查上架的资产信息
		if (Objects.isNull(authBefore) || Objects.equals(0L, authBefore)) {
			Long queryPutOn = iInnerService.queryPutOn(uid);
			userVO.setPutOnCount(queryPutOn);
		}
		Boolean vip = iInnerService.isVip(Longs.tryParse(uid));
		userVO.setVIPType(Objects.equals(vip, Boolean.TRUE) ? 1 : 0);
		userVO.setAuthBefore(authBefore);
		return userVO;
	}

	@Override
	public UserRegResponse register(UserRegRequest userRegRequest) {
		Long userReg = thirdService.userReg(userRegRequest.getPhone(), userRegRequest.getName());
		isTrue(Objects.isNull(userReg) || userReg.longValue() < 0, ErrorMessage.USER_REG_EX);
		return UserRegResponse.builder().phone(userRegRequest.getPhone()).appUid(userReg).name(userRegRequest.getName()).build();
	}

	@Override
	public TblUser infoWithUserId(Long userId) {
		LambdaQueryChainWrapper<TblUser> query = new LambdaQueryChainWrapper<>(baseMapper);
		return query.eq(TblUser::getAppUserId, userId).one();
	}

	@Override
	public boolean checkAuth(String uid, Long authCheckFrequency) {
		TblUser user = infoWithUserId(Longs.tryParse(uid));
		if (Objects.isNull(user)) {
			throw new ChainException(ErrorMessage.USER_NOT_EXIST);
		}
		Long queryAuthBefore = Optional.ofNullable(user).map(TblUser::getAuthBefore).orElse(0L);
		if (queryAuthBefore.longValue() == 0) {
			return true;
		}
		long minutesDifference = TimeUnit.MILLISECONDS.toMinutes((System.currentTimeMillis() - queryAuthBefore));
		return minutesDifference > authCheckFrequency;
	}
}
